package com.woniu.hander;

import com.woniu.service.SecurityService;
import com.woniu.util.JWTUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 处理非登录请求
 * 处理步骤
 * 1、拿到请求头中的jwt参数request
 *    第一种：没有带jwt，放行，放给其他过滤器执行，本类代码不执行
 *    第二种：带了
 * 2、请求头中带了jwt，需要解密
 *    第一种：判断是否带的合法，能否解开
 *    第二种：能解开
 * 3、能解开jwt，说明jwt是系统里的，判断是否自己登录成功后生成的jwt
 *
 */
@Component
public class JWTFilter extends OncePerRequestFilter {
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private SecurityService securityService;


    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String jwt = request.getHeader("jwt");
        if (jwt ==null){
            //让其他的过滤器去执行，本类代码终止这行
            filterChain.doFilter(request,response);
            return;
        }
        if (!JWTUtil.decode(jwt)){
            filterChain.doFilter(request,response);
            return;
        }

        Map map = JWTUtil.getPayLoad(jwt);
        String username =(String) map.get("username");
        //拿到redis jwt
        String redisJWT = redisTemplate.opsForValue().get("jwt:"+username);

        //redis 的没有对应的jwt（可能原因是过期了）
        if (redisJWT==null){
            //让其他的过滤器去执行，本类代码终止这行
            filterChain.doFilter(request,response);
            return;
        }

        //判断redis 的jwt和页面传过来的是否相等
        if (!jwt.equals(redisJWT)){
            //让其他的过滤器去执行，本类代码终止这行
            filterChain.doFilter(request,response);
            return;
        }

        //一直在调用系统，就需要给jwt续期
        redisTemplate.opsForValue().set("jwt:"+username,jwt,30, TimeUnit.MINUTES);

        //调用securityService获取username
        UserDetails userDetails = securityService.loadUserByUsername(username);
        UsernamePasswordAuthenticationToken upa = new UsernamePasswordAuthenticationToken(userDetails.getUsername(),userDetails.getPassword(),userDetails.getAuthorities());

        //把用户的信息放入springsecurity 容器里面
        SecurityContextHolder.getContext().setAuthentication(upa);
        //不断的给用户增加时间
        filterChain.doFilter(request,response);
    }
}
